package com.li.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.li.blog.common.aop.LogAnnotation;
import com.li.blog.dao.mapper.ArticleBodyMapper;
import com.li.blog.dao.mapper.ArticleMapper;
import com.li.blog.dao.dos.Archives;
import com.li.blog.dao.mapper.ArticleTagMapper;
import com.li.blog.dao.pojo.Article;
import com.li.blog.dao.pojo.ArticleBody;
import com.li.blog.dao.pojo.ArticleTag;
import com.li.blog.dao.pojo.SysUser;
import com.li.blog.service.*;
import com.li.blog.utils.UserThreadLocal;
import com.li.blog.vo.*;
import com.li.blog.vo.params.ArticleParam;
import com.li.blog.vo.params.PageParams;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
public class ArticleServiceImpl implements ArticleService {

  @Autowired
  private ArticleMapper articleMapper;
  @Autowired
  private TagService tagService;
  @Autowired
  private SysUserService sysUserService;
  @Autowired
  private ArticleTagMapper articleTagMapper;
  @Autowired
  private CommentsService commentsService;


  @Override
  @LogAnnotation(module = "文章", operation = "文章类表")
  public Result listArticle(PageParams pageParams) {
    Page<Article> page = new Page<>(pageParams.getPage(),pageParams.getPageSize());
    IPage<Article> articleIPage = this.articleMapper.listArticle(page,pageParams.getCategoryId(),pageParams.getTagId(),pageParams.getYear(),pageParams.getMonth());
    return Result.success(copyList(articleIPage.getRecords(),true,true));
  }

  //自定义注解 AOP日志
  //@Override
  //@LogAnnotation(module = "文章", operation = "文章类表")
  //public Result listArticle(PageParams pageParams) {
  //  Page<Article> page = new Page<>(pageParams.getPage(), pageParams.getPageSize());
  //  LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
  //
  //  //查询文章的参数 加上分类id，判断不为空 加上分类条件
  //  if (pageParams.getCategoryId() != null) {
  //    queryWrapper.eq(Article::getCategoryId,pageParams.getCategoryId());
  //  }
  //  /** order by create create_data desc 排序插件
  //        置顶排序 按照字段
  //        getCreateDate按照时间进行排序
  //        orderByDesc 可以传输多个数据
  //   */
  //  List<Long> articleIdList = new ArrayList<>();
  //  if (pageParams.getTagId() != null){
  //    LambdaQueryWrapper<ArticleTag> articleTagLambdaQueryWrapper = new LambdaQueryWrapper<>();
  //    articleTagLambdaQueryWrapper.eq(ArticleTag::getTagId,pageParams.getTagId());
  //    List<ArticleTag> articleTags = articleTagMapper.selectList(articleTagLambdaQueryWrapper);
  //    for (ArticleTag articleTag : articleTags) {
  //      articleIdList.add(articleTag.getArticleId());
  //    }
  //    if (articleIdList.size() > 0){
  //      queryWrapper.in(Article::getId,articleIdList);
  //    }
  //  }
  //  queryWrapper.orderByDesc(Article::getWeight, Article::getCreateDate);
  //  Page<Article> articlePage = articleMapper.selectPage(page, queryWrapper);
  //  List<Article> records = articlePage.getRecords();
  //  List<ArticleVo> articleVos = copyList(records, true, true);
  //  return Result.success(articleVos);
  //}

  @Override
  public Result hotArticle(int limit) {
    LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.orderByDesc(Article::getViewCounts);
    queryWrapper.select(Article::getId, Article::getTitle);
    queryWrapper.last("limit " + limit);
    List<Article> articles = articleMapper.selectList(queryWrapper);
    return Result.success(copyList(articles, false, false));
  }

  private List<ArticleVo> copyList(List<Article> records, boolean isTag, boolean isAuthor) {
    List<ArticleVo> articleVos = new ArrayList<>();
    for (Article record : records) {
      articleVos.add(copy(record, isTag, isAuthor, false, false));
    }
    return articleVos;
  }

  private List<ArticleVo> copyList(List<Article> records, boolean isTag, boolean isAuthor, boolean isBody) {
    List<ArticleVo> articleVoList = new ArrayList<>();
    for (Article record : records) {
      articleVoList.add(copy(record, isTag, isAuthor, isBody, false));
    }
    return articleVoList;
  }

  private List<ArticleVo> copyList(List<Article> records, boolean isTag, boolean isAuthor, boolean isBody, boolean isCategory) {
    List<ArticleVo> articleVoList = new ArrayList<>();
    for (Article record : records) {
      articleVoList.add(copy(record, isTag, isAuthor, isBody, isCategory));
    }
    return articleVoList;
  }


  @Override
  protected Object clone() throws CloneNotSupportedException {
    return super.clone();
  }

  private ArticleVo copy(Article article, boolean isTag, boolean isAuthor, boolean isBody, boolean isCategory) {
    ArticleVo articleVo = new ArticleVo();
    BeanUtils.copyProperties(article, articleVo);

    articleVo.setCreateDate(new DateTime(article.getCreateDate()).toString("yyyy-MM-dd HH:mm"));

    if (isTag) {
      Long articleId = article.getId();
      articleVo.setTags(tagService.findTagsByArticleId(articleId));
    }
    if (isAuthor) {
      Long authorId = article.getAuthorId();
      articleVo.setAuthor(sysUserService.findUserById(authorId).getNickname());
    }
    if (isBody) {
      ArticleBodyVo articleBody = findArticleBody(article.getId());
      articleVo.setBody(articleBody);
    }
    if (isCategory) {
      CategoryVo categoryVo = findCategory(article.getCategoryId());
      articleVo.setCategory(categoryVo);
    }
    Long articleId = article.getId();
    articleVo.setCommentCounts(commentsService.findAllCommentByArticleId(articleId));
    return articleVo;
  }

  @Autowired
  private CategoryService categoryService;

  private CategoryVo findCategory(Long categoryId) {
    return categoryService.findCategoryById(categoryId);
  }

  @Autowired
  private ArticleBodyMapper articleBodyMapper;

  private ArticleBodyVo findArticleBody(Long articleId) {
    LambdaQueryWrapper<ArticleBody> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(ArticleBody::getArticleId, articleId);
    ArticleBody articleBody = articleBodyMapper.selectOne(queryWrapper);
    ArticleBodyVo articleBodyVo = new ArticleBodyVo();
    articleBodyVo.setContent(articleBody.getContent());
    return articleBodyVo;
  }

  @Override
  public Result newArticles(int limit) {
    LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.orderByDesc(Article::getCreateDate);
    queryWrapper.select(Article::getId, Article::getTitle);
    queryWrapper.last("limit " + limit);
    //select id,title from article order by create_date desc limit 5
    List<Article> articles = articleMapper.selectList(queryWrapper);

    return Result.success(copyList(articles, false, false));
  }

  @Override
  public Result listArchives() {
    List<Archives> archivesList = articleMapper.listArchives();
    return Result.success(archivesList);
  }

  @Autowired
  private ThreadService threadService;

  @Override
  public ArticleVo findArticlerById(long id) {
    Article article = articleMapper.selectById(id);
    threadService.updateViewCount(articleMapper, article);
    return copy(article, true, true, true, true);
  }


  @Override
  @Transactional
  public Result publish(ArticleParam articleParam) {
    SysUser sysUser = UserThreadLocal.get();

    Article article = new Article();
    article.setAuthorId(sysUser.getId());
    article.setCategoryId(articleParam.getCategory().getId());
    article.setCreateDate(System.currentTimeMillis());
    article.setCommentCounts(0);
    article.setSummary(articleParam.getSummary());
    article.setTitle(articleParam.getTitle());
    article.setViewCounts(0);
    article.setWeight(Article.Article_Common);
    article.setBodyId(-1L);
    this.articleMapper.insert(article);

    //tags
    List<TagVo> tags = articleParam.getTags();
    if (tags != null) {
      for (TagVo tag : tags) {
        ArticleTag articleTag = new ArticleTag();
        articleTag.setArticleId(article.getId());
        articleTag.setTagId(tag.getId());
        this.articleTagMapper.insert(articleTag);
      }
    }
    ArticleBody articleBody = new ArticleBody();
    articleBody.setContent(articleParam.getBody().getContent());
    articleBody.setContentHtml(articleParam.getBody().getContentHtml());
    articleBody.setArticleId(article.getId());
    articleBodyMapper.insert(articleBody);

    article.setBodyId(articleBody.getId());
    articleMapper.updateById(article);
    ArticleVo articleVo = new ArticleVo();
    articleVo.setId(article.getId());
    return Result.success(articleVo);
  }
}
